package com.xqq;

import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import com.xqq.dao.ConflictEventDAO;
import com.xqq.dao.ConflictThermolDAO;
import com.xqq.dao.DisasterDAO;
import com.xqq.dao.PlaceDAO;
import com.xqq.service.CSVService;
import com.xqq.service.HeatmapService;
import com.xqq.service.JsonProcessorService;
import com.xqq.utils.WeatherJsonParser;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration;

import javax.annotation.Resource;


import java.sql.SQLOutput;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

//import static com.xqq.utils.GeoJSONParser.saveDisaster;
import static com.xqq.utils.GeoJSONParser.savePlace;


@SpringBootApplication(exclude = ElasticsearchRestClientAutoConfiguration.class)
@MapperScan({"com.xqq.mapper"})
public class MqConsumerApplication {
    public static JsonProcessorService myJsonProcessorService;

    @Resource
    public void setJonProcessorService(JsonProcessorService jsonProcessorService) {
        myJsonProcessorService = jsonProcessorService;
    }


    private static CSVService mycsvService;

    @Resource
    public void setCsvService(CSVService csvService) {
        mycsvService = csvService;
    }

    private static DisasterDAO mydisasterDAO;

    @Resource
    private void setDisasterDAO(DisasterDAO disasterDAO) {
        mydisasterDAO = disasterDAO;
    }

    ;

    private static PlaceDAO myPlaceDAO;

    @Resource
    private void setPlaceDAO(PlaceDAO placeDAO) {
        myPlaceDAO = placeDAO;
    }

    public static final String DATE_TIME_PATTERN_COMMON = "yyyy-MM-dd HH:mm:ss";
    ;

    @Resource
    private PlaceDAO placeDAO;


    private static HeatmapService myHeatmapService;

    @Resource
    private void setHeatmapService(HeatmapService heatmapService) {
        myHeatmapService = heatmapService;
    }

    //秒级时间戳 ->  yyyy-MM-dd HH:mm:ss
    public static String convertTimestampToStr(long timestamp) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_PATTERN_COMMON); // 根据需要调整格式
        Date date = new Date(timestamp * 1000);
        return sdf.format(date);
    }

    private static WeatherJsonParser myWeatherJsonParser;

    @Resource
    private void setMyWeatherJsonParser(WeatherJsonParser WeatherJsonParser) {
        myWeatherJsonParser = WeatherJsonParser;
    }
// 每天调用一下 刷新营地的定位时间
//        Long userId1 = 358463104122314752L;
//        String posoition1= "96.16065,23.63510";
//        Long userId2 = 360663254801207296L;
//        String posoition2= "96.16612,23.63448";
//        Long userId3 = 360663254809595904L;
//        String posoition3= "96.16071,23.63643";
//        RBucket<Object> positionBucket1 = redissonClient.getBucket(CommonUtil.getRedisKey(Constants.POSITION_PREFIX, String.valueOf(userId1)));
//        positionBucket1.set(posoition1 + Constants.SEMICOLON_DELIMITER + System.currentTimeMillis());
//        RBucket<Object> positionBucket2 = redissonClient.getBucket(CommonUtil.getRedisKey(Constants.POSITION_PREFIX, String.valueOf(userId2)));
//        positionBucket2.set(posoition2 + Constants.SEMICOLON_DELIMITER + System.currentTimeMillis());
//        RBucket<Object> positionBucket3 = redissonClient.getBucket(CommonUtil.getRedisKey(Constants.POSITION_PREFIX, String.valueOf(userId3)));
//        positionBucket3.set(posoition3 + Constants.SEMICOLON_DELIMITER + System.currentTimeMillis());

    public static void main(String[] args) throws ParseException {
        SpringApplication.run(MqConsumerApplication.class, args);
//        myJsonProcessorService.processJsonFile();
//        String beginDateStr = "2025-03-28";
//
//        String path = "F:\\Code\\Code_xwsk\\hour_liao.json";
//        int fireId = 1108;
//        String country = "东辽县";
//        myWeatherJsonParser.parsehouly(path,fireId,country);
////        myWeatherJsonParser.parseAddHourly(path,fireId,country,beginDateStr);
//
//        path = "F:\\Code\\Code_xwsk\\hour_feng.json";
//        fireId = 1109;
//        country = "东丰县";
//        myWeatherJsonParser.parsehouly(path,fireId,country);
////        myWeatherJsonParser.parseAddHourly(path, fireId, country, beginDateStr);
//
//        path = "F:\\Code\\Code_xwsk\\hour_xi.json";
//        fireId = 1106;
//        country = "西安区";
//        myWeatherJsonParser.parsehouly(path,fireId,country);
//
//        path = "F:\\Code\\Code_xwsk\\hour_long.json";
//        fireId = 1105;
//        country = "龙山区";
//        myWeatherJsonParser.parsehouly(path,fireId,country);
//        myWeatherJsonParser.parseAddHourly(path, fireId, country, beginDateStr);


//        savePlace(myPlaceDAO);

//        LocalDateTime now = LocalDateTime.now();
//        LocalDateTime roundedDown = now.truncatedTo(ChronoUnit.HOURS);
//        long datetimeEpoch = roundedDown.atZone(ZoneId.systemDefault()).toEpochSecond();
//        String s = convertTimestampToStr(datetimeEpoch);
//        System.out.println(s);
        myHeatmapService.generateHeatmap(300);

//        String originalData = "xqq";
//
//        // 编码为 Base64
//        String encodedData = Base64.getEncoder().encodeToString(originalData.getBytes());
//        System.out.println("Encoded: " + encodedData);
//        saveDisaster(mydisasterDAO);


//        String fileName = "Asia-Pacific_2018-2025_Jan31_2024_2025Myanmar";
//        String filePath = "F:\\XW\\项目相关\\缅甸\\冲突数据\\"+fileName+".csv";
//          String filePath = "F:\\XW\\项目相关\\缅甸\\冲突数据\\Asia-Pacific_2018-2025_May16_2024_2025_Myanmar.csv";
////        前期可执行 ConflictCsvParser,默认是先清空数据库再
//        mycsvService.readCsvAndSaveToDatabase(filePath,false);
//        mycsvService.readCsvAndAddToDatabase(filePath);
    }
}
//        myHeatmapService.generateHeatmap(300);
//        String fileName = "Asia-Pacific_2018-2024_Nov01";
//        String filePath = "F:\\我的星网\\项目相关\\缅甸\\冲突数据\\"+fileName+".csv";

//        String ouputPath = "F:\\我的星网\\项目相关\\"+fileName+"-split"+".csv";
//        try (CSVReader reader = new CSVReader(new FileReader(filePath));
//             CSVWriter writer = new CSVWriter(new FileWriter(ouputPath))) {
//            String[] nextLine;
//            while ((nextLine = reader.readNext()) != null) {
//                StringBuilder merged = new StringBuilder();
//                for (int i = 0; i < Math.min(nextLine.length, 60); i++) {
//                    merged.append(nextLine[i]);
//                }
//                // 将合并的字符串按分号分隔
////                String[] splitColumns = merged.toString().split(";");
////                writer.writeNext(splitColumns);
//                writer.writeNext(new String[]{merged.toString()});
//            }
//            System.out.println("合并分离完成，已保存为 " + ouputPath);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


////        //测试
////        Coordinate[] lineCoordinates = Arrays.stream(ROUTE_YINGDI_LEIJI_C.split(SEMICOLON_DELIMITER))
////                .map(position -> new Coordinate(Double.parseDouble(position.split(POSITION_DELIMITER)[0]), Double.parseDouble(position.split(POSITION_DELIMITER)[1])))
////                .collect(Collectors.toList())
////                .toArray(new Coordinate[ROUTE_YINGDI_LEIJI_C.split(SEMICOLON_DELIMITER).length]);

////        ArrayList<ConflictEventDO> conflictEventDOS = new ArrayList<>();
////        for (ConflictEventDO conflictEventDO : conflictEventDOList) {
////            Coordinate externalPointCoord = new Coordinate(conflictEventDO.getLongitude(), conflictEventDO.getLatitude());
////            Point externalPoint = geometryFactory.createPoint(externalPointCoord);
////            DistanceOp distanceOp = new DistanceOp(externalPoint, lineString);
////            Coordinate coordinate = distanceOp.nearestPoints()[1];
////            double positionDistance = calculateDistance(externalPointCoord.getX(), externalPointCoord.getY(), coordinate.getX(), coordinate.getY());
////            if(positionDistance<distance){
////                conflictEventDOS.add(conflictEventDO);
////            }
////        }

//查询路旁边的地点
//    public List<List<PlaceDO>> getPlaceFromRoad(List<String> positionList) {
//        long startTime = System.currentTimeMillis();
//        double distance = 200;
//        Set<Integer> hashSet = new HashSet<>();
//        List<PlaceDO> placeDOList = placeDAO.lambdaQuery().ne(PlaceDO::getType, 4).list();
//        List<List<PlaceDO>> placeDODoubleList = new ArrayList<>();
//        positionList.stream().forEach(position -> {
//            List<PlaceDO> placeDOS = new ArrayList<>();
//            for (PlaceDO placeDO : placeDOList) {
//                if(calculateDistance(placeDO.getPosition(), position)<distance&&!hashSet.contains(placeDO.getId())){
//                    placeDOS.add(placeDO);
//                    hashSet.add(placeDO.getId());
//                }
//            }
//            placeDODoubleList.add(placeDOS);
//        });
//        System.out.println("耗时: "+(System.currentTimeMillis()-startTime));
//        return placeDODoubleList;
//    }
//    static {
//        weatherConditionssMap = new HashMap<>();
//        weatherConditionssMap.put("Blowing Or Drifting Snow", "吹雪");
//        weatherConditionssMap.put("Heavy Freezing Drizzle/Freezing Rain", "冻雨");
//        weatherConditionssMap.put("Light Freezing Drizzle/Freezing Rain", "冻雨");
//        weatherConditionssMap.put("Freezing Fog", "冻雾");
//        weatherConditionssMap.put("Heavy Freezing Rain", "重度冻雨");
//        weatherConditionssMap.put("Light Freezing Rain", "轻微冻雨");
//        weatherConditionssMap.put("Funnel Cloud/Tornado", "龙卷风");
//        weatherConditionssMap.put("Hail Showers", "冰雹");
//        weatherConditionssMap.put("Ice", "冰");
//        weatherConditionssMap.put("Lightning Without Thunder", "无雷声闪电");
//        weatherConditionssMap.put("Mist", "轻雾");
//        weatherConditionssMap.put("Drizzle", "毛毛雨");
//        weatherConditionssMap.put("Precipitation In Vicinity", "附近有雨");
//        weatherConditionssMap.put("Rain", "雨");
//        weatherConditionssMap.put("Heavy Rain And Snow", "强雨雪");
//        weatherConditionssMap.put("Light Rain And Snow", "轻雨雪");
//        weatherConditionssMap.put("Rain Showers", "阵雨");
//        weatherConditionssMap.put("Heavy Rain", "大雨");
//        weatherConditionssMap.put("Light Rain", "小雨");
//        weatherConditionssMap.put("Sky Coverage Decreasing", "天空云量减少");
//        weatherConditionssMap.put("Sky Coverage Increasing", "天空云量增加");
//        weatherConditionssMap.put("Sky Unchanged", "天空无变化");
//        weatherConditionssMap.put("Heavy Drizzle", "小雨");
//        weatherConditionssMap.put("Smoke Or Haze", "烟或霾");
//        weatherConditionssMap.put("Snow", "雪");
//        weatherConditionssMap.put("Snow And Rain Showers", "雨夹雪");
//        weatherConditionssMap.put("Snow Showers", "阵雪");
//        weatherConditionssMap.put("Heavy Snow", "大雪");
//        weatherConditionssMap.put("Light Snow", "小雪");
//        weatherConditionssMap.put("Squalls", "飑风");
//        weatherConditionssMap.put("Thunderstorm", "雷暴");
//        weatherConditionssMap.put("Thunderstorm Without Precipitation", "无降水雷暴");
//        weatherConditionssMap.put("Diamond Dust", "钻石尘");
//        weatherConditionssMap.put("Light Drizzle", "毛毛雨");
//        weatherConditionssMap.put("Hail", "冰雹");
//        weatherConditionssMap.put("Overcast", "阴天");
//        weatherConditionssMap.put("Partially cloudy", "局部多云");
//        weatherConditionssMap.put("Clear", "晴朗");
//        weatherConditionssMap.put("Heavy Drizzle/Rain", "大雨");
//        weatherConditionssMap.put("Light Drizzle/Rain", "小雨");
//        weatherConditionssMap.put("Dust storm", "沙尘暴");
//        weatherConditionssMap.put("Fog", "雾");
//        weatherConditionssMap.put("Freezing Drizzle/Freezing Rain", "冻雨");
//    }
//}
////                uidList.stream().forEach(uid -> {
////                    //取这个用户最新的一条数据
////                    TbTrackDO tbTrackDO = tbTrackDAO.lambdaQuery()
////                            .orderByDesc(TbTrackDO::getGmtCreate)
////                            .eq(TbTrackDO::getUid, uid).
////                            last("limit 1").one();
////                    if (!ObjectUtils.isEmpty(tbTrackDO)) {
////                        String userName = userMap.get(uid) == null ? Constants.DEFAULT_USERNAME : userMap.get(uid).getRealName();
////                        TrackInfo trackInfo = TrackInfo.newBuilder()
////                                .setUid(String.valueOf(uid))
////                                .setUserName(userName)
////                                .setTaskId(String.valueOf(tbTrackDO.getTaskId()))
////                                .setPosition(tbTrackDO.getPosition())
////                                .setKeyPoint(tbTrackDO.getKeyPoint())
////                                .setContent(tbTrackDO.getContent())
////                                .setCreateTime(DateUtil.format(tbTrackDO.getGmtCreate(), Constants.DATE_TIME_PATTERN_COMMON))
////                                .setType(tbTrackDO.getType())
////                                .build();
////                        normalTrackList.add(trackInfo);
////                    }
////                });
//============================================================================================
//    public AllTrackInfo queryAllUserTrackByDate(String date, int pageNumber, int pageSize) {
//        List<Long> uidList = tbUserImeiDAO.lambdaQuery()
//                .eq(TbUserImeiDO::getDeleted, NOT_DELETED)
//                .list().stream().map(TbUserImeiDO::getUid).distinct().collect(Collectors.toList());
//        Map<Long, TbUserDO> userMap =
//                tbUserDAO.lambdaQuery().in(TbUserDO::getUid, uidList).list().stream().collect(Collectors.toMap(TbUserDO::getUid, user -> user));
//
//        List<TbTrackDO> trackDOList = new ArrayList<>();
//        Page<TbTrackDO> page = new Page<>(pageNumber, pageSize);
//        LambdaQueryWrapper<TbTrackDO> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(TbTrackDO::getDate, date)
//                .in(TbTrackDO::getUid, uidList)
//                .orderByDesc(TbTrackDO::getGmtCreate);
//        Page<TbTrackDO> tbTrackDOPage = tbTrackDAO.page(page, queryWrapper);
//        trackDOList.addAll(tbTrackDOPage.getRecords());
//        int totalPage = (int) (tbTrackDOPage.getTotal() % pageSize == 0 ? (tbTrackDOPage.getTotal() / pageSize) : (tbTrackDOPage.getTotal() / pageSize + 1));
//        List<TrackInfo> normalTrackList = new ArrayList<>();
//        //去redis中取最新的点位
//        if (pageNumber <= Constants.DEFAULT_PAGE_NUMBER) {
//            normalTrackList = fetchLatestTracksFromRedis(uidList, userMap);
//        }
//        if (trackDOList.isEmpty()) {
//            return buildAllTrackInfo(normalTrackList, new ArrayList<>(), pageNumber, totalPage);
//        }
//        List<TrackInfo> trackInfoList = trackDOList.stream()
//                .map(track ->  buildTrackInfo(track, userMap.get(track.getUid())))
//                .collect(Collectors.toList());
//        return AllTrackInfo.newBuilder()
//                .addAllNormalTrackInfo(normalTrackList)
//                .addAllOtherTrackInfo(trackInfoList)
//                .setPageNumber(pageNumber)
//                .setTotalPage(totalPage).build();
//    }
//    private List<TrackInfo> fetchLatestTracksFromRedis(List<Long> uidList, Map<Long, TbUserDO> userMap) {
//        return uidList.stream()
//                .map(uid -> {
//                    RBucket<String> positionBucket = redissonClient.getBucket(CommonUtil.getRedisKey(Constants.POSITION_PREFIX, String.valueOf(uid)));
//                    String bucketPt = positionBucket.get();
//                    if (bucketPt != null) {
//                        String[] parts = bucketPt.split(Constants.SEMICOLON_DELIMITER);
//                        Integer type = tbUserImeiDAO.lambdaQuery()
//                                .eq(TbUserImeiDO::getDeleted, Constants.UN_DELETE_STATUS)
//                                .eq(TbUserImeiDO::getUid, uid)
//                                .one().getType();
//                        return TrackInfo.newBuilder()
//                                .setUid(String.valueOf(uid))
//                                .setUserName(userMap.get(uid).getRealName())
//                                .setPosition(parts[0])
//                                .setCreateTime(parts[1])
//                                .setKeyPoint(1)
//                                .setType(type != null ? type : 0)
//                                .build();
//                    }
//                    return null;
//                })
//                .filter(Objects::nonNull)
//                .sorted(Comparator.comparing(TrackInfo::getCreateTime).reversed())
//                .collect(Collectors.toList());
//    }
//
//    private TrackInfo buildTrackInfo(TbTrackDO track, TbUserDO user) {
//        return TrackInfo.newBuilder()
//                .setUid(String.valueOf(user.getUid()))
//                .setUserName(user.getRealName())
//                .setTaskId(String.valueOf(track.getTaskId()))
//                .setPosition(track.getPosition())
//                .setKeyPoint(track.getKeyPoint())
//                .setContent(track.getContent())
//                .setCreateTime(DateUtil.format(track.getGmtCreate(), Constants.DATE_TIME_PATTERN_COMMON))
//                .setType(track.getType())
//                .build();
//    }
//
//    private AllTrackInfo buildAllTrackInfo(List<TrackInfo> normalTrackList, List<TrackInfo> otherTrackList, int pageNumber, int totalPage) {
//        return AllTrackInfo.newBuilder()
//                .addAllNormalTrackInfo(normalTrackList)
//                .addAllOtherTrackInfo(otherTrackList)
//                .setPageNumber(pageNumber)
//                .setTotalPage(totalPage)
//                .build();
//    }

//    @Override
//    @Transactional
//    public CommonResponse createThermolConflict(CreateThermolConflictReq createThermolConflictReq) {
//        int numClusters = createThermolConflictReq.getClusterCount() == 0 ? Constants.DEFAULT_CLUSTER_COUNT : createThermolConflictReq.getClusterCount();
//        // Step 1: Fetch data from the database
//        List<ConflictEventDO> records = conflictEventDAO.list();
//        // Step 2: Prepare data for clustering
//        List<GeoPoint> geoPoints = new ArrayList<>();
//        for (ConflictEventDO record : records) {
//            geoPoints.add(new GeoPoint(record.getLatitude(), record.getLongitude()));
//        }
//
//        // Step 3: Perform K-means clustering
//        KMeansPlusPlusClusterer<GeoPoint> clusterer = new KMeansPlusPlusClusterer<>(numClusters);
//        List<CentroidCluster<GeoPoint>> cluster1 = clusterer.cluster(geoPoints);
//
//        // Step 4: Prepare results
//        List<ConflictThermolDO> results = new ArrayList<>();
//        for (Cluster<GeoPoint> cluster : cluster1) {
//            double[] centroid = new double[2];
//            for (GeoPoint point : cluster.getPoints()) {
//                centroid[0] += point.getPoint()[0];
//                centroid[1] += point.getPoint()[1];
//            }
//            centroid[0] /= cluster.getPoints().size();
//            centroid[1] /= cluster.getPoints().size();
//            ConflictThermolDO thermolDO = new ConflictThermolDO();
//            thermolDO.setLatitude(Double.parseDouble(String.format("%.6f", centroid[0])));
//            thermolDO.setLongitude(Double.parseDouble(String.format("%.6f", centroid[1])));
//            thermolDO.setCount(cluster.getPoints().size());
//            results.add(thermolDO);
//        }
//        System.out.println(Arrays.toString(results.toArray()));
//        conflictThermolDAO.remove(new LambdaQueryWrapper<>());
//        conflictThermolDAO.saveBatch(results);
//        return CommonResponse.newBuilder()
//                .setMessage(Constants.SUCCESS_MSG)
//                .setCode(Constants.SUCCESS_CODE)
//                .build();
//    }
